package com.agileai.bpm.common;

import java.util.ArrayList;
import java.util.List;

import com.agileai.bpm.domain.define.Activity.ActTypes;
import com.agileai.bpm.model.ActivitiesDocument.Activities;
import com.agileai.bpm.model.AuditActivityType;
import com.agileai.bpm.model.ControlType;
import com.agileai.bpm.model.EndActivityType;
import com.agileai.bpm.model.ForkActivityType;
import com.agileai.bpm.model.InvokeActivityType;
import com.agileai.bpm.model.JoinActivityType;
import com.agileai.bpm.model.ManualActivityType;
import com.agileai.bpm.model.ProcessDefineDocument;
import com.agileai.bpm.model.ProcessDefineDocument.ProcessDefine;
import com.agileai.bpm.model.StartActivityType;
import com.agileai.bpm.model.TransitionType;
import com.agileai.bpm.model.TransitionsDocument.Transitions;
import com.agileai.bpm.model.WatchActivityType;
import com.agileai.common.KeyGenerator;

public class ProcessDefineHelper {

	public ProcessDefineDocument createProcessDefine(String processId,String processCode,String processName){
		KeyGenerator keyGenerator = KeyGenerator.instance(); 
		
		ProcessDefineDocument defineDocument = ProcessDefineDocument.Factory.newInstance();
		ProcessDefine processDefine = defineDocument.addNewProcessDefine();
		processDefine.setId(processId);
		processDefine.setName(processName);
		processDefine.setCode(processCode);
		
		Activities activities = processDefine.addNewActivities();
		String startActivityId = keyGenerator.genKey(); 
		StartActivityType startActivityType = activities.addNewStartActivity();
		startActivityType.setId(startActivityId);
		startActivityType.setCode("rect1");
		startActivityType.setName("开始");
		
		
		String manualActivityId = keyGenerator.genKey();
		ManualActivityType manualActivityType = activities.addNewManualActivity();
		manualActivityType.setId(manualActivityId);
		manualActivityType.setCode("rect2");
		manualActivityType.setName("填写表单");
		
		String endActivityId = keyGenerator.genKey(); 
		EndActivityType endActivityType = activities.addNewEndActivity();
		endActivityType.setId(endActivityId);
		endActivityType.setCode("rect3");
		endActivityType.setName("结束");
		
		Transitions transitions = processDefine.addNewTransitions();
		
		String transition1Id = keyGenerator.genKey();
		TransitionType transitionType1 = transitions.addNewTransition();
		transitionType1.setId(transition1Id);
		transitionType1.setFrom(startActivityId);
		transitionType1.setTo(manualActivityId);
		transitionType1.setCode("path4");
		transitionType1.setName("TO 填写表单");
		
		
		String transition2Id = keyGenerator.genKey();
		TransitionType transitionType2 = transitions.addNewTransition();
		transitionType2.setId(transition2Id);
		transitionType2.setFrom(manualActivityId);
		transitionType2.setTo(endActivityId);
		transitionType2.setCode("path5");
		transitionType2.setName("TO 结束");
		
		return defineDocument;
	}
	
	public void createActivity(ProcessDefineDocument processDefineDocument
			,String activityId,String activityType,String  activityCode,String activityName){
		ProcessDefine processDefine = processDefineDocument.getProcessDefine();
		Activities activities = processDefine.getActivities();
		if (activityType.equals(ActTypes.manual)){
			ManualActivityType manualActivityType = activities.addNewManualActivity();
			manualActivityType.setId(activityId);
			manualActivityType.setCode(activityCode);
			manualActivityType.setName(activityName);
		}
		else if (activityType.equals(ActTypes.audit)){
			AuditActivityType auditActivityType = activities.addNewAuditActivity();
			auditActivityType.setId(activityId);
			auditActivityType.setCode(activityCode);
			auditActivityType.setName(activityName);
		}
		else if (activityType.equals(ActTypes.invoke)){
			InvokeActivityType invokeActivityType = activities.addNewInvokeActivity();
			invokeActivityType.setId(activityId);
			invokeActivityType.setCode(activityCode);
			invokeActivityType.setName(activityName);
		}
		else if (activityType.equals(ActTypes.watch)){
			WatchActivityType watchActivityType = activities.addNewWatchActivity();
			watchActivityType.setId(activityId);
			watchActivityType.setCode(activityCode);
			watchActivityType.setName(activityName);
		}
		else if (activityType.equals(ActTypes.fork)){
			ForkActivityType forkActivityType = activities.addNewForkActivity();
			forkActivityType.setId(activityId);
			forkActivityType.setCode(activityCode);
			forkActivityType.setName(activityName);
			forkActivityType.setControlType(ControlType.AND);
		}
		else if (activityType.equals(ActTypes.join)){
			JoinActivityType joinActivityType = activities.addNewJoinActivity();
			joinActivityType.setId(activityId);
			joinActivityType.setCode(activityCode);
			joinActivityType.setName(activityName);
			joinActivityType.setControlType(ControlType.AND);
		}	
		else if (activityType.equals(ActTypes.start)){
			StartActivityType startActivityType = activities.addNewStartActivity();
			startActivityType.setId(activityId);
			startActivityType.setCode(activityCode);
			startActivityType.setName(activityName);
		}	
		else if (activityType.equals(ActTypes.end)){
			EndActivityType endActivityType = activities.addNewEndActivity();
			endActivityType.setId(activityId);
			endActivityType.setCode(activityCode);
			endActivityType.setName(activityName);
		}			
	}
	
	public void deleteActivity(ProcessDefineDocument processDefineDocument,String activityId){
		ProcessDefine processDefine = processDefineDocument.getProcessDefine();
		Activities activities = processDefine.getActivities();
		
		StartActivityType startActivityType = activities.getStartActivity();
		if (startActivityType != null && startActivityType.getId().equals(activityId)){
			startActivityType.setNil();
		}
		
		EndActivityType endActivityType = activities.getEndActivity();
		if (endActivityType != null && endActivityType.getId().equals(activityId)){
			endActivityType.setNil();
		}
		
		ManualActivityType[] manualActivityTypes = activities.getManualActivityArray();
		if (manualActivityTypes != null && manualActivityTypes.length > 0){
			for (int i=0;i < manualActivityTypes.length;i++){
				ManualActivityType manualActivityType = manualActivityTypes[i];
				if (manualActivityType.getId().equals(activityId)){
					activities.removeManualActivity(i);
					break;
				}
			}
		}
		
		AuditActivityType[] auditActivityTypes = activities.getAuditActivityArray();
		if (auditActivityTypes != null && auditActivityTypes.length > 0){
			for (int i=0;i < auditActivityTypes.length;i++){
				AuditActivityType auditActivityType = auditActivityTypes[i];
				if (auditActivityType.getId().equals(activityId)){
					activities.removeAuditActivity(i);
					break;
				}
			}
		}
		
		InvokeActivityType[] invokeActivityTypes = activities.getInvokeActivityArray();
		if (invokeActivityTypes != null && invokeActivityTypes.length > 0){
			for (int i=0;i < invokeActivityTypes.length;i++){
				InvokeActivityType invokeActivityType = invokeActivityTypes[i];
				if (invokeActivityType.getId().equals(activityId)){
					activities.removeInvokeActivity(i);
					break;
				}
			}
		}
		
		WatchActivityType[] watchActivityTypes = activities.getWatchActivityArray();
		if (watchActivityTypes != null && watchActivityTypes.length > 0){
			for (int i=0;i < watchActivityTypes.length;i++){
				WatchActivityType watchActivityType = watchActivityTypes[i];
				if (watchActivityType.getId().equals(activityId)){
					activities.removeWatchActivity(i);
					break;
				}
			}
		}
		
		ForkActivityType[] forkActivityTypes = activities.getForkActivityArray();
		if (forkActivityTypes != null && forkActivityTypes.length > 0){
			for (int i=0;i < forkActivityTypes.length;i++){
				ForkActivityType forkActivityType = forkActivityTypes[i];
				if (forkActivityType.getId().equals(activityId)){
					activities.removeForkActivity(i);
					break;
				}
			}
		}
		
		JoinActivityType[] joinActivityTypes = activities.getJoinActivityArray();
		if (joinActivityTypes != null && joinActivityTypes.length > 0){
			for (int i=0;i < joinActivityTypes.length;i++){
				JoinActivityType joinActivityType = joinActivityTypes[i];
				if (joinActivityType.getId().equals(activityId)){
					activities.removeJoinActivity(i);
					break;
				}
			}
		}
		
		List<String> transitonIds = this.retrieveTransitionIdList(processDefineDocument, activityId);
		this.deleteTransitions(processDefineDocument, transitonIds);
	}
	
	public void createTransition(ProcessDefineDocument processDefineDocument
			,String transitionId,String transitionCode,String fromActivityId,String toActivityId){
		ProcessDefine processDefine = processDefineDocument.getProcessDefine();
		TransitionType transitionType = processDefine.getTransitions().addNewTransition();
		transitionType.setId(transitionId);
		transitionType.setCode(transitionCode);
		transitionType.setFrom(fromActivityId);
		transitionType.setTo(toActivityId);
	}
	
	public void deleteTransition(ProcessDefineDocument processDefineDocument
			,String transitionId){
		ProcessDefine processDefine = processDefineDocument.getProcessDefine();
		Transitions transitions = processDefine.getTransitions();
		if (transitions != null){
			TransitionType[] transitionTypes = transitions.getTransitionArray();
			for (int i = 0;i < transitionTypes.length;i++){
				TransitionType transitionType = transitionTypes[i];
				if (transitionId.equals(transitionType.getId())){
					transitions.removeTransition(i);
					return;
				}
			}
		}
	}
	
	
	public List<String> retrieveTransitionIdList(ProcessDefineDocument processDefineDocument
			,String activityId){
		List<String> result = new ArrayList<String>();
		ProcessDefine processDefine = processDefineDocument.getProcessDefine();
		Transitions transitions = processDefine.getTransitions();
		if (transitions != null){
			TransitionType[] transitionTypes = transitions.getTransitionArray();
			for (int i = 0;i < transitionTypes.length;i++){
				TransitionType transitionType = transitionTypes[i];
				if (transitionType.getFrom().equals(activityId) || transitionType.getTo().equals(activityId)){
					result.add(transitionType.getId());
				}
			}
		}
		return result;
	}
	
	private void deleteTransitions(ProcessDefineDocument processDefineDocument
			,List<String> transitionIds){
		if (transitionIds != null && transitionIds.size() > 0 ){
			for (int i=0;i < transitionIds.size();i++){
				String transitionId = transitionIds.get(i);
				deleteTransition(processDefineDocument, transitionId);
			}
		}
	}
	
	public String retreiveActivityId(ProcessDefineDocument processDefineDocument,String activityCode){
		String result = null;
		
		ProcessDefine processDefine = processDefineDocument.getProcessDefine();
		Activities activities = processDefine.getActivities();
		StartActivityType startActivityType = activities.getStartActivity();
		EndActivityType endActivityType = activities.getEndActivity();
		if (startActivityType.getCode().equals(activityCode)){
			result = startActivityType.getId();
		}
		else if (endActivityType.getCode().equals(activityCode)){
			result = endActivityType.getId();
		}
		else{
			ManualActivityType[] manualActivityTypes = activities.getManualActivityArray();
			if (manualActivityTypes != null){
				for (int i=0;i < manualActivityTypes.length;i++){
					ManualActivityType manualActivityType = manualActivityTypes[i];
					if (manualActivityType.getCode().equals(activityCode)){
						result = manualActivityType.getId();
						break;
					}
				}
			}
			
			AuditActivityType[] auditActivityTypes = activities.getAuditActivityArray();
			if (auditActivityTypes != null){
				for (int i=0;i < auditActivityTypes.length;i++){
					AuditActivityType manualActivityType = auditActivityTypes[i];
					if (manualActivityType.getCode().equals(activityCode)){
						result = manualActivityType.getId();
						break;
					}
				}
			}
			
			InvokeActivityType[] invokeActivityTypes = activities.getInvokeActivityArray();
			if (invokeActivityTypes != null){
				for (int i=0;i < invokeActivityTypes.length;i++){
					InvokeActivityType manualActivityType = invokeActivityTypes[i];
					if (manualActivityType.getCode().equals(activityCode)){
						result = manualActivityType.getId();
						break;
					}
				}
			}
			
			WatchActivityType[] watchActivityTypes = activities.getWatchActivityArray();
			if (watchActivityTypes != null){
				for (int i=0;i < watchActivityTypes.length;i++){
					WatchActivityType manualActivityType = watchActivityTypes[i];
					if (manualActivityType.getCode().equals(activityCode)){
						result = manualActivityType.getId();
						break;
					}
				}
			}
			
			ForkActivityType[] forkActivityTypes = activities.getForkActivityArray();
			if (forkActivityTypes != null){
				for (int i=0;i < forkActivityTypes.length;i++){
					ForkActivityType manualActivityType = forkActivityTypes[i];
					if (manualActivityType.getCode().equals(activityCode)){
						result = manualActivityType.getId();
						break;
					}
				}
			}
			
			JoinActivityType[] joinActivityTypes = activities.getJoinActivityArray();
			if (joinActivityTypes != null){
				for (int i=0;i < joinActivityTypes.length;i++){
					JoinActivityType manualActivityType = joinActivityTypes[i];
					if (manualActivityType.getCode().equals(activityCode)){
						result = manualActivityType.getId();
						break;
					}
				}
			}
		}
		return result;
	}
}
